home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / pvm34b3.zip / pvm34b3 / pvm3 / src / host.c < prev    next >
C/C++ Source or Header  |  1997-07-22  |  21KB  |  1,014 lines

  1.  
  2. static char rcsid[] =
  3.     "$Id: host.c,v 1.10 1997/06/27 17:32:21 pvmsrc Exp $";
  4.  
  5. /*
  6.  *         PVM version 3.4:  Parallel Virtual Machine System
  7.  *               University of Tennessee, Knoxville TN.
  8.  *           Oak Ridge National Laboratory, Oak Ridge TN.
  9.  *                   Emory University, Atlanta GA.
  10.  *      Authors:  J. J. Dongarra, G. E. Fagg, M. Fischer
  11.  *          G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci,
  12.  *         P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam
  13.  *                   (C) 1997 All Rights Reserved
  14.  *
  15.  *                              NOTICE
  16.  *
  17.  * Permission to use, copy, modify, and distribute this software and
  18.  * its documentation for any purpose and without fee is hereby granted
  19.  * provided that the above copyright notice appear in all copies and
  20.  * that both the copyright notice and this permission notice appear in
  21.  * supporting documentation.
  22.  *
  23.  * Neither the Institutions (Emory University, Oak Ridge National
  24.  * Laboratory, and University of Tennessee) nor the Authors make any
  25.  * representations about the suitability of this software for any
  26.  * purpose.  This software is provided ``as is'' without express or
  27.  * implied warranty.
  28.  *
  29.  * PVM version 3 was funded in part by the U.S. Department of Energy,
  30.  * the National Science Foundation and the State of Tennessee.
  31.  */
  32.  
  33. /*
  34.  *    host.c
  35.  *
  36.  *    Host table functions.
  37.  *
  38. $Log: host.c,v $
  39.  * Revision 1.10  1997/06/27  17:32:21  pvmsrc
  40.  * Updated for WIN32 header files & Authors.
  41.  *
  42.  * Revision 1.9  1997/06/24  20:39:16  pvmsrc
  43.  * Eliminated unnecessary global externs.
  44.  *
  45.  * Revision 1.8  1997/04/30  21:25:56  pvmsrc
  46.  * SGI Compiler Warning Cleanup.
  47.  *
  48.  * Revision 1.7  1997/04/09  14:38:20  pvmsrc
  49.  * PVM patches from the base 3.3.10 to 3.3.11 versions where applicable.
  50.  * Originals by Bob Manchek. Altered by Graham Fagg where required.
  51.  *
  52.  * Revision 1.6  1997/01/28  19:26:17  pvmsrc
  53.  * New Copyright Notice & Authors.
  54.  *
  55.  * Revision 1.5  1996/10/25  14:04:44  pvmsrc
  56.  * changed ifdef around ioctl for AIX 3.x/4.x to use IMA_arch-class
  57.  *
  58.  * Revision 1.4  1996/10/25  13:57:17  pvmsrc
  59.  * Replaced old #includes for protocol headers:
  60.  *     - <pvmsdpro.h>, "ddpro.h", "tdpro.h"
  61.  * With #include of new combined header:
  62.  *     - <pvmproto.h>
  63.  *
  64.  * Revision 1.3  1996/10/24  21:04:45  pvmsrc
  65.  * Moved #include of "global.h" down below other headers:
  66.  *     - need to have all of the structures / types declared before
  67.  *         the globals can be declared...
  68.  *
  69.  * Revision 1.2  1996/10/24  18:14:07  pvmsrc
  70.  * ifdefs to ioctl call parameter for AIX3.x/4.x difference
  71.  *
  72.  * Revision 1.1  1996/09/23  23:44:08  pvmsrc
  73.  * Initial revision
  74.  *
  75.  * Revision 1.10  1996/05/13  20:25:48  manchek/GEF
  76.  * missing pvmlogerror in readhostfile
  77.  *
  78.  * Revision 1.9  1995/11/02  16:01:49  manchek
  79.  * use NET_IF_IN_SYS if include/sys/net/if.h
  80.  *
  81.  * Revision 1.8  1995/07/28  16:51:30  manchek
  82.  * ifdef for UTS2
  83.  *
  84.  * Revision 1.7  1995/05/17  16:09:13  manchek
  85.  * added HF_OVERLOAD and '$' syntax
  86.  *
  87.  * Revision 1.6  1994/10/15  19:05:39  manchek
  88.  * must use PVM_FREE instead of free in iflist()
  89.  *
  90.  * Revision 1.5  1994/06/21  18:30:55  manchek
  91.  * HF_SPEED flag now determines whether hd_speed has been set
  92.  *
  93.  * Revision 1.4  1994/06/03  20:38:14  manchek
  94.  * version 3.3.0
  95.  *
  96.  * Revision 1.3  1993/11/30  19:52:05  manchek
  97.  * readhostfile() puts defaults in ht_hosts[0]
  98.  *
  99.  * Revision 1.2  1993/09/15  15:03:31  manchek
  100.  * defined max() if not already there
  101.  *
  102.  * Revision 1.1  1993/08/30  23:26:47  manchek
  103.  * Initial revision
  104.  *
  105.  */
  106.  
  107. #ifndef WIN32
  108. #include <sys/param.h>
  109. #endif
  110. #ifdef NEEDMENDIAN
  111. #include <machine/endian.h>
  112. #endif
  113. #ifdef NEEDENDIAN
  114. #include <endian.h>
  115. #endif
  116. #ifdef NEEDSENDIAN
  117. #include <sys/endian.h>
  118. #endif
  119.  
  120. #ifdef WIN32
  121. #include "pvmwin.h"
  122. #include "..\xdr\types.h"
  123. #include "..\xdr\xdr.h"
  124. #else
  125. #include <rpc/types.h>
  126. #include <rpc/xdr.h>
  127. #ifndef IMA_TITN
  128. #include <sys/types.h>
  129. #include <sys/ioctl.h>
  130. #else
  131. #include <bsd/sys/types.h>
  132. #include <sys/43ioctl.h>
  133. #endif
  134. #include <sys/time.h>
  135. #include <sys/socket.h>
  136. #include <netinet/in.h>
  137. #ifdef    NET_IF_IN_SYS
  138. #include <sys/net/if.h>
  139. #else
  140. #include <net/if.h>
  141. #endif
  142. #include <netdb.h>
  143. #endif
  144.  
  145. #include <stdio.h>
  146.  
  147. #ifdef    SYSVSTR
  148. #include <string.h>
  149. #else
  150. #include <strings.h>
  151. #endif
  152. #include <ctype.h>
  153. #include <pvm3.h>
  154. #include <pvmproto.h>
  155. #include "pvmalloc.h"
  156. #include "host.h"
  157. #include "pmsg.h"
  158. #include "pkt.h"
  159. #include "bfunc.h"
  160. #include "global.h"
  161.  
  162. #ifndef    max
  163. #define    max(a,b)    ((a)>(b)?(a):(b))
  164. #endif
  165.  
  166. #ifdef SOCKADHASLEN
  167. #define SIZ(p) max(sizeof(p), (p).sa_len)
  168. #else
  169. #define SIZ(p) sizeof(p)
  170. #endif
  171.  
  172.  
  173. char *inadport_decimal();
  174.  
  175.  
  176. /***************
  177.  **  Globals  **
  178.  **           **
  179.  ***************/
  180.  
  181. extern int pvmdebmask;                /* from pvmd.c */
  182. extern int tidhmask;                /* from pvmd.c */
  183.  
  184.  
  185. /***************
  186.  **  Private  **
  187.  **           **
  188.  ***************/
  189.  
  190.  
  191. /*****************
  192.  **  Interface  **
  193.  **             **
  194.  *****************/
  195.  
  196. /*    hd_new()
  197. *
  198. *    Make a new host descriptor.
  199. */
  200.  
  201. struct hostd *
  202. hd_new(hh)
  203.     int hh;        /* index in host table */
  204. {
  205.     struct hostd *hp;
  206.  
  207.     if (hp = TALLOC(1, struct hostd, "hd")) {
  208.         BZERO((char*)hp, sizeof(struct hostd));
  209.         hp->hd_ref = 1;
  210.         hp->hd_hostpart = hh << (ffs(tidhmask) - 1);
  211.         hp->hd_sad.sin_family = AF_INET;
  212.         hp->hd_txq = pk_new(0);
  213.         hp->hd_opq = pk_new(0);
  214.         hp->hd_rxq = pk_new(0);
  215.         hp->hd_txseq = 1;
  216.         hp->hd_rxseq = 1;
  217.         hp->hd_speed = 1000;
  218.         hp->hd_rtt.tv_sec = 1;    /* XXX const */
  219.         hp->hd_mcas = mca_new();
  220.     }
  221.     return hp;
  222. }
  223.  
  224.  
  225. /*    hd_free()
  226. *
  227. *    Free a host descriptor and all associated storage.
  228. *    Probably want to use hd_unref() instead.
  229. */
  230.  
  231. void
  232. hd_free(hp)
  233.     struct hostd *hp;
  234. {
  235.     struct mca *mcap;
  236.  
  237.     if (hp->hd_name)
  238.         PVM_FREE(hp->hd_name);
  239.     if (hp->hd_arch)
  240.         PVM_FREE(hp->hd_arch);
  241.     if (hp->hd_login)
  242.         PVM_FREE(hp->hd_login);
  243.     if (hp->hd_dpath)
  244.         PVM_FREE(hp->hd_dpath);
  245.     if (hp->hd_epath)
  246.         PVM_FREE(hp->hd_epath);
  247.     if (hp->hd_bpath)
  248.         PVM_FREE(hp->hd_bpath);
  249.     if (hp->hd_wdir)
  250.         PVM_FREE(hp->hd_wdir);
  251.     if (hp->hd_sopts)
  252.         PVM_FREE(hp->hd_sopts);
  253.     if (hp->hd_txq)
  254.         pk_free(hp->hd_txq);
  255.     if (hp->hd_opq)
  256.         pk_free(hp->hd_opq);
  257.     if (hp->hd_rxq)
  258.         pk_free(hp->hd_rxq);
  259.     if (hp->hd_rxm)
  260.         pmsg_unref(hp->hd_rxm);
  261.     if (mcap = hp->hd_mcas) {
  262.         while (mcap->mc_link != mcap)
  263.             mca_free(mcap->mc_link);
  264.         mca_free(mcap);
  265.     }
  266.     if (hp->hd_aname)
  267.         PVM_FREE(hp->hd_aname);
  268.     PVM_FREE(hp);
  269. }
  270.  
  271.  
  272. /*    hd_unref()
  273. *
  274. *    Decrement the refcount of a host descriptor.  Free it if count
  275. *    reaches zero.
  276. */
  277.  
  278. void
  279. hd_unref(hp)
  280.     struct hostd *hp;
  281. {
  282.     if (--hp->hd_ref < 1)
  283.         hd_free(hp);
  284. }
  285.  
  286.  
  287. void
  288. hd_dump(hp)
  289.     struct hostd *hp;
  290. {
  291.     int n;
  292.     struct pkt *pp, *pp2;
  293.  
  294.     pvmlogprintf(
  295.             " hd_dump() ref %d t 0x%x n \"%s\" a \"%s\" ar \"%s\" dsig 0x%x\n",
  296.             hp->hd_ref,
  297.             hp->hd_hostpart,
  298.             (hp->hd_name ? hp->hd_name : ""),
  299.             (hp->hd_aname ? hp->hd_aname : ""),
  300.             (hp->hd_arch ? hp->hd_arch : ""),
  301.             hp->hd_dsig);
  302.  
  303.     pvmlogprintf(
  304.             "           lo \"%s\" so \"%s\" dx \"%s\" ep \"%s\" bx \"%s\" wd \"%s\" sp %d\n",
  305.             (hp->hd_login ? hp->hd_login : ""),
  306.             (hp->hd_sopts ? hp->hd_sopts : ""),
  307.             (hp->hd_dpath ? hp->hd_dpath : ""),
  308.             (hp->hd_epath ? hp->hd_epath : ""),
  309.             (hp->hd_bpath ? hp->hd_bpath : ""),
  310.             (hp->hd_wdir ? hp->hd_wdir : ""),
  311.             hp->hd_speed);
  312.  
  313.     n = 0;
  314.     if (pp2 = hp->hd_txq)
  315.         for (pp = pp2->pk_link; pp != pp2; pp = pp->pk_link)
  316.             n++;
  317.     pvmlogprintf("           sa %s mtu %d f 0x%x e %d txq %d\n",
  318.             inadport_decimal(&hp->hd_sad),
  319.             hp->hd_mtu,
  320.             hp->hd_flag,
  321.             hp->hd_err,
  322.             n);
  323.  
  324.     pvmlogprintf(
  325.             "           tx %d rx %d rtt %d.%06d\n",
  326.             hp->hd_txseq, hp->hd_rxseq,
  327.             hp->hd_rtt.tv_sec, hp->hd_rtt.tv_usec);
  328. }
  329.  
  330.  
  331. /*    nametohost()
  332. *
  333. *    Get a host descriptor by hostname.
  334. */
  335.  
  336. struct hostd *
  337. nametohost(htp, name)
  338.     struct htab *htp;
  339.     char *name;
  340. {
  341.     int hh;
  342.     struct hostd *hp;
  343.  
  344.     if (!strcmp(name, "."))
  345.         return htp->ht_hosts[htp->ht_local];
  346.  
  347.     for (hh = htp->ht_last; hh > 0; hh--)
  348.         if ((hp = htp->ht_hosts[hh]) && !strcmp(name, hp->hd_name))
  349.             return hp;
  350.     return (struct hostd*)0;
  351. }
  352.  
  353.  
  354. /*    indtohost()
  355. *
  356. *    Get a host descriptor by its host table index.
  357. */
  358.  
  359. struct hostd *
  360. indtohost(htp, n)
  361.     struct htab *htp;
  362.     int n;
  363. {
  364.     return (n >= 1 && n <= htp->ht_last) ? htp->ht_hosts[n] : 0;
  365. }
  366.  
  367.  
  368. /*    tidtohost()
  369. *
  370. *    Get a host descriptor by its tid.
  371. */
  372.  
  373. struct hostd *
  374. tidtohost(htp, tid)
  375.     struct htab *htp;
  376.     int tid;
  377. {
  378.     return indtohost(htp, (tid & tidhmask) >> (ffs(tidhmask) - 1));
  379. }
  380.  
  381.  
  382. /*    ht_free()
  383. *
  384. *    Free a host table and unref all hosts in it.
  385. */
  386.  
  387. void
  388. ht_free(htp)
  389.     struct htab *htp;
  390. {
  391.     int i;
  392.  
  393.     for (i = 1; i <= htp->ht_last; i++)
  394.         if (htp->ht_hosts[i])
  395.             hd_unref(htp->ht_hosts[i]);
  396.     PVM_FREE(htp->ht_hosts);
  397.     PVM_FREE(htp);
  398. }
  399.  
  400.  
  401. /*    ht_new()
  402. *
  403. *    Make a new (empty) host table.  Length is advisory as ht_hosts
  404. *    is extended as needed.
  405. */
  406.  
  407. struct htab *
  408. ht_new(siz)
  409.     int siz;        /* initial length of ht_hosts[] */
  410. {
  411.     struct htab *htp;
  412.  
  413.     if (siz < 1)
  414.         siz = 1;
  415.     htp = TALLOC(1, struct htab, "ht1");
  416.     BZERO((char*)htp, sizeof(struct htab));
  417.     htp->ht_last = siz;
  418.     htp->ht_hosts = TALLOC(siz + 1, struct hostd*, "ht2");
  419.     BZERO((char*)htp->ht_hosts, (siz + 1) * sizeof(struct hostd*));
  420.     return htp;
  421. }
  422.  
  423.  
  424. /*    ht_insert()
  425. *
  426. *    Add a host to a host table.  Extend ht_hosts if necessary.
  427. *    Update ht_narch.
  428. */
  429.  
  430. void
  431. ht_insert(htp, hp)
  432.     struct htab *htp;
  433.     struct hostd *hp;
  434. {
  435.     int hh;
  436.     int i;
  437.     unsigned long mask = 0, tmpmask;
  438.  
  439.     hh = (hp->hd_hostpart & tidhmask) >> (ffs(tidhmask) - 1);
  440.  
  441.     /* extend ht_hosts[] if no room */
  442.  
  443.     if (hh > htp->ht_last) {
  444.         int n = htp->ht_last;
  445.  
  446.         htp->ht_last = (hh * 3) / 2;
  447.         htp->ht_hosts = TREALLOC(htp->ht_hosts, htp->ht_last + 1, struct hostd*);
  448.         while (++n <= htp->ht_last)
  449.             htp->ht_hosts[n] = 0;
  450.     }
  451.  
  452.     /* if already have an entry, take this as an update XXX kind of a hack */
  453.  
  454.     if (htp->ht_hosts[hh]) {    /* already have an entry */
  455.  
  456.         struct hostd *hp2 = htp->ht_hosts[hh];
  457.  
  458.         if (hp->hd_name) {
  459.             if (hp2->hd_name)
  460.                 PVM_FREE(hp2->hd_name);
  461.             hp2->hd_name = STRALLOC(hp->hd_name);
  462.         }
  463.         if (hp->hd_arch) {
  464.             if (hp2->hd_arch)
  465.                 PVM_FREE(hp2->hd_arch);
  466.             hp2->hd_arch = STRALLOC(hp->hd_arch);
  467.         }
  468.         hp2->hd_dsig = hp->hd_dsig;
  469.         hp2->hd_mtu = hp->hd_mtu;
  470.         hp2->hd_sad = hp->hd_sad;
  471.         hp2->hd_speed = hp->hd_speed;
  472.  
  473.     } else {                    /* add new entry */
  474.  
  475.         htp->ht_hosts[hh] = hp;
  476.         if (hh)
  477.             htp->ht_cnt++;
  478.         hp->hd_ref++;
  479.     }
  480.  
  481.     /* update number of arches */
  482.  
  483. /*
  484.     htp->ht_narch = 0;
  485.     for (hh = htp->ht_last; hh > 0; hh--) {
  486.         hp = htp->ht_hosts[hh];
  487.         if (hp && hp->hd_arch) {
  488.             i = pvm_archcode(htp->ht_hosts[hh]->hd_arch);
  489.             tmpmask = (1 << i);
  490.             if (tmpmask & ~mask)
  491.                 htp->ht_narch++;
  492.             mask |= tmpmask;
  493.         }
  494.     }
  495. */
  496. }
  497.  
  498.  
  499. /*    ht_delete()
  500. *
  501. *    Remove a host from a host table and unreference it.
  502. */
  503.  
  504. void
  505. ht_delete(htp, hp)
  506.     struct htab *htp;
  507.     struct hostd *hp;
  508. {
  509.     int hh;
  510.     int i;
  511.     unsigned long mask = 0, tmpmask;
  512.  
  513.     hh = (hp->hd_hostpart & tidhmask) >> (ffs(tidhmask) - 1);
  514.     if (hh < 0 || hh > htp->ht_last || htp->ht_hosts[hh] != hp) {
  515.         pvmlogerror("ht_delete() host not in table\n");
  516.         return;
  517.     }
  518.     htp->ht_hosts[hh] = 0;
  519.     if (hh)
  520.         htp->ht_cnt--;
  521.  
  522.     hd_unref(hp);
  523.  
  524.     /* update number of arches */
  525.  
  526. /*
  527.     htp->ht_narch = 0;
  528.     for (hh = htp->ht_last; hh > 0; hh--) {
  529.         if (!(hp = htp->ht_hosts[hh]))
  530.             continue;
  531.         if (hp->hd_arch) {
  532.             i = pvm_archcode(htp->ht_hosts[hh]->hd_arch);
  533.             tmpmask = (1 << i);
  534.             if (tmpmask & ~mask)
  535.                 htp->ht_narch++;
  536.             mask |= tmpmask;
  537.         }
  538.     }
  539. */
  540. }
  541.  
  542.  
  543. void
  544. ht_dump(htp)
  545.     struct htab *htp;
  546. {
  547.     int hh;
  548.  
  549.     pvmlogprintf(
  550. "ht_dump() ser %d last %d cnt %d master %d cons %d local %d narch %d\n",
  551.             htp->ht_serial, htp->ht_last, htp->ht_cnt, htp->ht_master,
  552.             htp->ht_cons, htp->ht_local, htp->ht_narch);
  553.     for (hh = 0; hh <= htp->ht_last; hh++)
  554.         if (htp->ht_hosts[hh])
  555.             hd_dump(htp->ht_hosts[hh]);
  556. }
  557.  
  558.  
  559. /*    ht_merge()
  560. *
  561. *    Add entries in src host table to dst host table.
  562. */
  563.  
  564. int
  565. ht_merge(dst, src)
  566.     struct htab *dst, *src;
  567. {
  568.     int hh;
  569.     struct hostd *hp;
  570.  
  571.     for (hh = src->ht_last; hh > 0; hh--)
  572.         if (hp = src->ht_hosts[hh])
  573.             ht_insert(dst, hp);
  574.     return 0;
  575. }
  576.  
  577.  
  578. /*    applydefaults()
  579. *
  580. *    Apply default settings to unspecified fields of hostd.
  581. */
  582.  
  583. int
  584. applydefaults(hp, defhp)
  585.     struct hostd *hp;        /* hostd to modify */
  586.     struct hostd *defhp;    /* default settings */
  587. {
  588.     if (!hp->hd_login && defhp->hd_login)
  589.         hp->hd_login = STRALLOC(defhp->hd_login);
  590.  
  591.     if (!hp->hd_dpath && defhp->hd_dpath)
  592.         hp->hd_dpath = STRALLOC(defhp->hd_dpath);
  593.  
  594.     if (!hp->hd_epath && defhp->hd_epath)
  595.         hp->hd_epath = STRALLOC(defhp->hd_epath);
  596.  
  597.     if (!hp->hd_bpath && defhp->hd_bpath)
  598.         hp->hd_bpath = STRALLOC(defhp->hd_bpath);
  599.  
  600.     if (!hp->hd_wdir && defhp->hd_wdir)
  601.         hp->hd_wdir = STRALLOC(defhp->hd_wdir);
  602.  
  603.     if (!hp->hd_sopts && defhp->hd_sopts)
  604.         hp->hd_sopts = STRALLOC(defhp->hd_sopts);
  605.  
  606.     if (!hp->hd_aname && defhp->hd_aname)
  607.         hp->hd_aname = STRALLOC(defhp->hd_aname);
  608.  
  609.     if (!(hp->hd_flag & HF_SPEED) && (defhp->hd_flag & HF_SPEED))
  610.         hp->hd_speed = defhp->hd_speed;
  611.  
  612.     hp->hd_flag |= defhp->hd_flag;
  613.  
  614.     return 0;
  615. }
  616.  
  617.  
  618. /*    parsehost()
  619. *
  620. *    Parse hostfile line into hostd.
  621. */
  622.  
  623. int
  624. parsehost(buf, hp)
  625.     char *buf;
  626.     struct hostd *hp;
  627. {
  628.     char *av[10];        /* parsed words */
  629.     int ac;
  630.     int err = 0;
  631.  
  632.     ac = sizeof(av)/sizeof(av[0]);
  633.     if (acav(buf, &ac, av)) {
  634.         pvmlogprintf("parsehost(): line too long\n");
  635.         goto bad;
  636.     }
  637.     if (!ac)
  638.         goto bad;
  639.  
  640.     /* add options to host descriptor */
  641.  
  642.     while (--ac > 0) {
  643.         if (!strncmp(av[ac], "lo=", 3)) {
  644.             if (hp->hd_login)
  645.                 PVM_FREE(hp->hd_login);
  646.             hp->hd_login = STRALLOC(av[ac] + 3);
  647.             continue;
  648.         }
  649.         if (!strncmp(av[ac], "dx=", 3)) {
  650.             if (hp->hd_dpath)
  651.                 PVM_FREE(hp->hd_dpath);
  652.             hp->hd_dpath = STRALLOC(av[ac] + 3);
  653.             continue;
  654.         }
  655.         if (!strncmp(av[ac], "ep=", 3)) {
  656.             if (hp->hd_epath)
  657.                 PVM_FREE(hp->hd_epath);
  658.             hp->hd_epath = STRALLOC(av[ac] + 3);
  659.             continue;
  660.         }
  661.         if (!strncmp(av[ac], "sp=", 3)) {
  662.             hp->hd_speed = atoi(av[ac] + 3);
  663.             hp->hd_flag |= HF_SPEED;
  664.             continue;
  665.         }
  666.         if (!strncmp(av[ac], "bx=", 3)) {
  667.             if (hp->hd_bpath)
  668.                 PVM_FREE(hp->hd_bpath);
  669.             hp->hd_bpath = STRALLOC(av[ac] + 3);
  670.             continue;
  671.         }
  672.         if (!strncmp(av[ac], "wd=", 3)) {
  673.             if (hp->hd_wdir)
  674.                 PVM_FREE(hp->hd_wdir);
  675.             hp->hd_wdir = STRALLOC(av[ac] + 3);
  676.             continue;
  677.         }
  678.         if (!strncmp(av[ac], "so=", 3)) {
  679.             if (hp->hd_sopts)
  680.                 PVM_FREE(hp->hd_sopts);
  681.             hp->hd_sopts = STRALLOC(av[ac] + 3);
  682.             continue;
  683.         }
  684.         if (!strncmp(av[ac], "ip=", 3)) {
  685.             if (hp->hd_aname)
  686.                 PVM_FREE(hp->hd_aname);
  687.             hp->hd_aname = STRALLOC(av[ac] + 3);
  688.             continue;
  689.         }
  690.         pvmlogprintf("parsehost(): unknown option \"%s\"\n", av[ac]);
  691.         err++;
  692.     }
  693.     if (err)
  694.         goto bad;
  695.  
  696.     if (hp->hd_name)
  697.         PVM_FREE(hp->hd_name);
  698.     hp->hd_name = STRALLOC(av[0]);
  699.     return 0;
  700.  
  701. bad:
  702.     return -1;
  703. }
  704.  
  705.  
  706. /*    readhostfile()
  707. *
  708. *    Read a host file and return host table with options and ipaddrs
  709. *    filled in.
  710. */
  711.  
  712. struct htab *
  713. readhostfile(fn)
  714.     char *fn;
  715. {
  716.     struct htab *htp;
  717.     struct hostd *hp;
  718.     FILE *ff = 0;
  719.     char buf[512];        /* line buffer */
  720.     int lnum = 0;        /* line counter */
  721.     int err = 0;        /* error count */
  722.     struct hostent *he;
  723.     char *p;
  724.     struct in_addr *my_in_addrs;
  725.     int num_addrs;
  726.     int i;
  727.     int maxhostid = tidhmask >> (ffs(tidhmask) - 1);
  728.     struct hostd *defaults = 0;
  729.  
  730.     htp = ht_new(1);
  731.  
  732.     /*
  733.     * get list of this host's interfaces so we can detect ourself in file
  734.     */
  735.  
  736.     if (iflist(&my_in_addrs, &num_addrs) == -1 || num_addrs < 1) {
  737.         pvmlogprintf("readhostfile() iflist failed\n");
  738.         goto bail;
  739.     }
  740.  
  741.     if (!(ff = fopen(fn, "r"))) {
  742.         pvmlogprintf("readhostfile() %s: can't read\n", fn);
  743.         goto bail;
  744.     }
  745.  
  746.     /* parse each line of host file */
  747.  
  748.     while (fgets(buf, sizeof(buf), ff)) {
  749.         lnum++;
  750.         for (p = buf; *p && isspace(*p); p++);
  751.  
  752.         if (!*p || *p == '#')    /* leading '#' is comment */
  753.             continue;
  754.  
  755.         if (lnum > maxhostid) {
  756.             pvmlogprintf("readhostfile() %s: too many lines\n", fn);
  757.             err++;
  758.             break;
  759.         }
  760.         hp = hd_new(lnum);
  761.  
  762.         while (*p == '&' || *p == '$') {
  763.             if (*p == '&')        /* leading '&' is no-start */
  764.                 hp->hd_flag |= HF_NOSTART;
  765.             if (*p == '$')        /* leading '$' allows overloading host */
  766.                 hp->hd_flag |= HF_OVERLOAD;
  767.             p++;
  768.         }
  769.  
  770.         if (parsehost(p, hp)) {
  771.             pvmlogprintf("readhostfile() %s %d: errors\n", fn, lnum);
  772.             err++;
  773.             goto badline;
  774.         }
  775.  
  776.     /*
  777.     * if host == "*", change the default options
  778.     * instead of adding a new host to the list
  779.     */
  780.  
  781.         if (!strcmp(hp->hd_name, "*")) {
  782.             if (defaults)
  783.                 hd_unref(defaults);
  784.             defaults = hp;
  785.             continue;
  786.         }
  787.  
  788.     /* Set unspecified fields of hp to defaults */
  789.  
  790.         if (defaults)
  791.             applydefaults(hp, defaults);
  792.  
  793.     /* look up ip addr */
  794.  
  795.         if (!(he = gethostbyname(hp->hd_aname ? hp->hd_aname : hp->hd_name))) {
  796.             pvmlogprintf("readhostfile() %s %d: %s: can't gethostbyname\n",
  797.                 fn, lnum, hp->hd_name);
  798.             err++;
  799.             goto badline;
  800.         }
  801.         BCOPY(he->h_addr_list[0], (char*)&hp->hd_sad.sin_addr,
  802.             sizeof(struct in_addr));
  803.  
  804.     /* mark master host to not start */
  805.  
  806.         if (!(hp->hd_flag & HF_OVERLOAD))
  807.             for (i = num_addrs; i-- > 0; ) {
  808.                 if (BCMP((char*)&my_in_addrs[i], (char*)&hp->hd_sad.sin_addr,
  809.                         sizeof(struct in_addr)) == 0) {
  810.                     hp->hd_flag |= HF_NOSTART;
  811.                     break;
  812.                 }
  813.             }
  814.  
  815.         ht_insert(htp, hp);
  816.         hd_unref(hp);
  817.         continue;
  818.  
  819. badline:
  820.         hd_unref(hp);
  821.     }
  822.     if (err) {
  823.         pvmlogprintf("readhostfile() %s: %d errors in hostfile\n", fn, err);
  824.     }
  825.  
  826.     if (defaults) {
  827.         defaults->hd_hostpart = 0;
  828.         ht_insert(htp, defaults);
  829.     }
  830.     fclose(ff);
  831.     return htp;
  832.  
  833. bail:
  834.     if (defaults)
  835.         hd_unref(defaults);
  836.     if (ff)
  837.         fclose(ff);
  838.     ht_free(htp);
  839.     return (struct htab*)0;
  840. }
  841.  
  842.  
  843. /*    iflist()
  844. *
  845. *    Return list of addresses for active network interfaces.
  846. */
  847.  
  848. #ifdef    SIOCGIFCONF
  849.  
  850. int
  851. iflist(alp, np)
  852.     struct in_addr **alp;    /* return list of addresses */
  853.     int *np;                /* return len of alp */
  854. {
  855.     int soc = -1;                        /* socket */
  856.     static struct in_addr *iplist = 0;    /* list of interface addrs found */
  857.     int nip = 0;                        /* length of iplist */
  858.     char buf[4096];                        /* return space for SIOCGIOCONF */
  859.     struct ifconf sif;
  860.     struct ifreq *reqp;
  861.     struct ifreq req;
  862.     char *cp;
  863.  
  864.     if (iplist)
  865.         PVM_FREE(iplist);
  866.     iplist = TALLOC(10, struct in_addr, "ifl");
  867.  
  868.     if ((soc = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
  869.         perror("socket");
  870.         goto bail;
  871.     }
  872.  
  873.     sif.ifc_ifcu.ifcu_buf = buf;
  874.     sif.ifc_len = sizeof(buf);
  875.     if (ioctl(soc,
  876. #ifdef OSIOCGIFCONF
  877. #if defined(IMA_RS6K) || defined(IMA_RS6KMP) || defined(IMA_SP2MPI)
  878.         SIOCGIFCONF
  879. #else
  880.         OSIOCGIFCONF
  881. #endif
  882. #else
  883.         SIOCGIFCONF
  884. #endif
  885.         , &sif) == -1) {
  886.         perror("ioctl");
  887.         goto bail;
  888.     }
  889.  
  890.     for (cp = sif.ifc_ifcu.ifcu_buf;
  891.             cp - sif.ifc_ifcu.ifcu_buf < sif.ifc_len;
  892.             cp += sizeof(*reqp) - sizeof(struct sockaddr) + SIZ(reqp->ifr_addr))
  893.     {
  894.         reqp = (struct ifreq*)cp;
  895.         if (reqp->ifr_addr.sa_family != AF_INET)
  896.             continue;
  897.         BCOPY(reqp->ifr_name, req.ifr_name, sizeof(req.ifr_name));
  898.         if (ioctl(soc, SIOCGIFFLAGS, &req) == -1) {
  899.             perror("ioctl");
  900.             goto bail;
  901.         }
  902.         if (IFF_UP & req.ifr_ifru.ifru_flags) {
  903.             if (nip > 0 && !(nip % 10))
  904.                 iplist = TREALLOC(iplist, (nip + 10), struct in_addr);
  905.             iplist[nip++] =
  906.             ((struct sockaddr_in*)(&reqp->ifr_ifru.ifru_addr))->sin_addr;
  907.             if (pvmdebmask & PDMNET) {
  908.                 long a;
  909.  
  910.                 a = ((struct sockaddr_in*)(&reqp->ifr_ifru.ifru_addr))->sin_addr.s_addr;
  911.                 a = ntohl(a);
  912.                 pvmlogprintf("iflist() %s %d.%d.%d.%d\n",
  913.                         reqp->ifr_name,
  914.                         0xff & (a >> 24),
  915.                         0xff & (a >> 16),
  916.                         0xff & (a >> 8),
  917.                         0xff & a);
  918.             }
  919.         }
  920.     }
  921.  
  922.     *alp = iplist;
  923.     *np = nip;
  924.     return 0;
  925.  
  926. bail:
  927.     (void)close(soc);
  928.     return -1;
  929. }
  930.  
  931. #else    /*SIOCGIFCONF*/
  932.  
  933. int
  934. iflist(alp, np)
  935.     struct in_addr **alp;    /* return list of addresses */
  936.     int *np;                /* return len of alp */
  937. {
  938.     static struct in_addr *iplist = 0;    /* list of interface addrs found */
  939.     int nip = 0;                        /* length of iplist */
  940.     char hn[MAXHOSTNAMELEN];
  941.     struct hostent *he;
  942.     char **p;
  943.  
  944.     if (iplist)
  945.         PVM_FREE(iplist);
  946.     iplist = TALLOC(10, struct in_addr, "ifl");
  947.  
  948.     if (gethostname(hn, sizeof(hn))) {
  949.         perror("gethostname");
  950.         goto bail;
  951.     }
  952.     if (!(he = gethostbyname(hn))) {
  953.         fprintf(stderr, "can't gethostbyname\n");
  954.         goto bail;
  955.     }
  956.     for (; he->h_addr_list[nip]; nip++) {
  957.         if (nip > 0 && !(nip % 10))
  958.             iplist = TREALLOC(iplist, (nip + 10), struct in_addr);
  959.         iplist[nip].s_addr = ((struct in_addr*)(he->h_addr_list[nip]))->s_addr;
  960.     }
  961.  
  962.     *alp = iplist;
  963.     *np = nip;
  964.     return 0;
  965.  
  966. bail:
  967.     return -1;
  968. }
  969.  
  970. #endif    /*SIOCGIFCONF*/
  971.  
  972.  
  973. /*    acav()
  974. *
  975. *    Parse a string into words separated by whitespace.
  976. *    Max number of words is original value of *acp.
  977. *
  978. *    Trashes out the original string.
  979. *    Returns 0 with av[0]..av[*acp - 1] pointing to the words.
  980. *    Returns 1 if too many words.
  981. */
  982.  
  983. int
  984. acav(s, acp, av)
  985.     char *s;        /* the string to parse */
  986.     int *acp;        /* max words in, ac out */
  987.     char **av;        /* pointers to args */
  988. {
  989.     register int ac;
  990.     register char *p = s;
  991.     register int n = *acp;
  992.  
  993.     /* separate out words of command */
  994.  
  995.     ac = 0;
  996.     while (*p) {
  997.         while (isspace(*p)) p++;
  998.         if (*p) {
  999.             if (ac >= n) {
  1000.     /* command too long */
  1001.                 *acp = ac;
  1002.                 return 1;
  1003.             }
  1004.             av[ac++] = p;
  1005.             while (*p && !isspace(*p)) p++;
  1006.             if (*p) *p++ = 0;
  1007.         }
  1008.     }
  1009.     *acp = ac;
  1010.     return 0;
  1011. }
  1012.  
  1013.  
  1014.